package com.su.gulimall.product.service.impl;


import com.su.common.constant.ProductConstant;
import com.su.common.to.SkuHasStockVo;
import com.su.common.to.SkuReductionTo;
import com.su.common.to.SpuBoundTo;
import com.su.common.to.es.SkuEsModel;
import com.su.common.utils.R;
import com.su.gulimall.product.entity.*;
import com.su.gulimall.product.feign.CouponFeignService;
import com.su.gulimall.product.feign.SearchFeignService;
import com.su.gulimall.product.feign.WareFeignService;
import com.su.gulimall.product.service.*;
import com.su.gulimall.product.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.su.common.utils.PageUtils;
import com.su.common.utils.Query;

import com.su.gulimall.product.dao.SpuInfoDao;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;


@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {


    @Autowired
    SpuInfoDescService spuInfoDescService;

    @Autowired
    SpuImagesService imagesService;

    @Autowired
    AttrService attrService;

    @Autowired
    SkuInfoService skuInfoService;

    @Autowired
    SkuImagesService skuImagesService;

    @Autowired
    SkuSaleAttrValueService skuSaleAttrValueService;

    @Autowired
    ProductAttrValueService productAttrValueService;
    @Autowired
    CouponFeignService couponFeignService;
    @Autowired
    BrandService brandService;
    @Autowired
    CategoryService categoryService;
    @Autowired
    WareFeignService wareFeignService;
    @Autowired
    SearchFeignService searchFeignService;
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }
    @Transactional
    @Override
    public void saveBaseSpuInfo (SpuInfoEntity infoEntity){
        this.baseMapper.insert(infoEntity);
    }

    @Override
    public void saveSpuInfoDesc (SpuInfoDescEntity infoDescEntity){
        spuInfoDescService.save(infoDescEntity);
    }

    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params) {
        QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();
        String key = (String) params.get("key");
        if(!StringUtils.isEmpty(key))
        {
          wrapper.and(w->{
             w.eq("id",key).or().like("spu_name",key);
          });
        }
        String status = (String) params.get("status");
        if(!StringUtils.isEmpty(status))
        {
            wrapper.eq("publish_status",status);
        }
        String catelogId = (String) params.get("catelogId");
        if(!StringUtils.isEmpty(catelogId)&&!"0".equalsIgnoreCase(catelogId))
        {
            wrapper.eq("catalog_id",catelogId);
        }
        String brandId = (String) params.get("brandId");
        if((!StringUtils.isEmpty(brandId)&&!"0".equalsIgnoreCase(brandId)))
        {
            wrapper.eq("brand_id",brandId);
        }
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                wrapper
        );
        return new PageUtils(page);
    }
    //商品的保存
    @Override
    public void saveSpuInfo(SpuSaveVo vos) {
        //1.保存商品的基本信息 spu_info
        SpuInfoEntity infoEntity = new SpuInfoEntity();
        //属性的对拷功能
        BeanUtils.copyProperties(vos, infoEntity);
        infoEntity.setCreateTime(new Date());
        infoEntity.setUpdateTime(new Date());
        this.saveBaseSpuInfo(infoEntity);
        //2.保存spu的描述图片 spu_info_desc
        List<String> decriptList = vos.getDecript();
        SpuInfoDescEntity infoDescEntity = new SpuInfoDescEntity();
        infoDescEntity.setSpuId(infoEntity.getId());
        infoDescEntity.setDecript(String.join(",", decriptList));
        this.saveSpuInfoDesc(infoDescEntity);
        //3.保存spu的图片集 spu_images
        List<String> images = vos.getImages();
        //这里可能出现字段设置问题
        imagesService.saveImages(infoEntity.getId(), images);
        //4.保存spu的规格参数 product_attr_value
        List<BaseAttrs> baseAttrsList = vos.getBaseAttrs();
        List<ProductAttrValueEntity> collect = baseAttrsList.stream().map((attr) -> {
            ProductAttrValueEntity entity = new ProductAttrValueEntity();
            entity.setAttrId(attr.getAttrId());
            //这个表中没有属性的名字，所以要根据属性的名，此时可以根据属性的Id查出属性实体，然后在找到名字即可
            AttrEntity byId = attrService.getById(attr.getAttrId());
            entity.setAttrName(byId.getAttrName());
            entity.setAttrValue(attr.getAttrValues());
            entity.setQuickShow(attr.getShowDesc());
            entity.setSpuId(infoEntity.getId());
            return entity;
        }).collect(Collectors.toList());
        productAttrValueService.saveProductAttr(collect);
        //5.保存所有的sku信息，以及spu的远程调用优惠信息
        Bounds bounds = vos.getBounds();
        SpuBoundTo spuBoundTo = new SpuBoundTo();
        BeanUtils.copyProperties(bounds,spuBoundTo);
        spuBoundTo.setSpuId(infoEntity.getId());
        //调用远程服务的某个具体方法
        R r1 = couponFeignService.saveSpuBounds(spuBoundTo);
        if(r1.getCode()==0)
        {
            System.out.println("此处远程服务调用执行成功");
        }
        //获取所有的sku信息，并存储在列表中
        List<Skus> skusList = vos.getSkus();
        if (skusList != null && skusList.size() > 0) {
            skusList.forEach(item -> {
                String defaultImg = "";
                for (Images image : item.getImages()) {
                    if (image.getDefaultImg() == 1) {
                        defaultImg = image.getImgUrl();
                    }
                }
                //5.1 sku基本信息 sku_info
                SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
                BeanUtils.copyProperties(item, skuInfoEntity);
                skuInfoEntity.setBrandId(infoEntity.getBrandId());
                skuInfoEntity.setCatalogId(infoEntity.getCatalogId());
                skuInfoEntity.setSaleCount(0L);
                skuInfoEntity.setSpuId(infoEntity.getId());
                skuInfoEntity.setSkuDefaultImg(defaultImg);
                skuInfoEntity.setSkuDesc("暂时未处理");
                skuInfoService.saveSkuInfo(skuInfoEntity);
                //自动生成sku的id
                Long skuId = skuInfoEntity.getSkuId();
                List<SkuImagesEntity> imagesEntities = item.getImages().stream().map(img -> {
                    SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                    skuImagesEntity.setSkuId(skuId);
                    skuImagesEntity.setImgUrl(img.getImgUrl());
                    skuImagesEntity.setDefaultImg(img.getDefaultImg());
                    return skuImagesEntity;
                }).filter(entity -> {
                    //返回值为false，则会被忽略该实体类
                    return !StringUtils.isEmpty(entity.getImgUrl());
                }).collect(Collectors.toList());
                //5.2 sku的图片信息 sku_image
                skuImagesService.saveBatch(imagesEntities);
                //5.3 sku的销售属性信息 sku_sale_attr_value
                List<Attr> attr = item.getAttr();
                List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = attr.stream().map(a -> {
                    SkuSaleAttrValueEntity attrValueEntity = new SkuSaleAttrValueEntity();
                    BeanUtils.copyProperties(a, attrValueEntity);
                    attrValueEntity.setSkuId(skuId);
                    return attrValueEntity;
                }).collect(Collectors.toList());
                skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntities);
                //5.4 sku的优惠，满减信息 sms_sku_ladder/sms_sku_full_reduction/sms_member_price/
                SkuReductionTo skuReductionTo = new SkuReductionTo();
                BeanUtils.copyProperties(item,skuReductionTo);
                skuReductionTo.setSkuId(skuId);
                if(skuReductionTo.getFullCount()>0 || skuReductionTo.getReducePrice().compareTo(new BigDecimal(0))==1)
                {
                    R r = couponFeignService.saveSkuReduction(skuReductionTo);
                    if(r.getCode()==0)
                    {
                        System.out.println("============");
                        System.out.println("我已经执行到这里了");
                        System.out.println("执行成功");

                    }else {
                        System.out.println("============");
                        System.out.println("我已经执行到这里了");
                        System.out.println("执行失败");
                    }
                }

            });
        }
    }
    //商品的状态更新，传递过来商品的spuId;
    @Override
    public void updateState(Long spuId) {
        //查询当前spuId对应的所有skuId,操作sku——info表;
        List<SkuInfoEntity> skus=skuInfoService.getInfosBySpuId(spuId);
        //遍历skus实体类，获取id封装为一个long列表，便于后续操作
        //TODO：4.查询该sku下的可以被用来检索的规格属性
        List<Long> skuList = skus.stream()
                .map(SkuInfoEntity::getSkuId)
                .collect(Collectors.toList());
        //封装sku的信息
        //根据spuId在productAttrValue表查出来所有的商品属性值信息
        List<ProductAttrValueEntity> baseAttrs = productAttrValueService.baseAttrlistforspu(spuId);
        //根据实体类获取Id
        List<Long> attrIds = baseAttrs.stream().map(attr -> {
             return attr.getAttrId();
        }).collect(Collectors.toList());
        //根据所有属性的id在attr表找出该实体类；
        //获取实体类中的id值（需要满足search_type=1且属性id在传过来的属性id列表中）
        List<Long> searchAttr=attrService.queryNotInAttrId(attrIds);
        //将具备查询功能的属性id放入set集合
        Set<Long> idSet = new HashSet<>(searchAttr);
        //拿总属性进行相关过滤排除
        //到此处已经准备了可检索的属性，并封装在attrs
        List<SkuEsModel.Attrs> attrs = baseAttrs.stream().filter(item -> {
            return idSet.contains(item.getAttrId());
        }).map(item->{
            //封装给esmodel模型
            SkuEsModel.Attrs attrs1 = new SkuEsModel.Attrs();
            BeanUtils.copyProperties(item,attrs1);
            return attrs1;
        }).collect(Collectors.toList());
        Map<Long, Boolean> stockMap =null;
        //TODO:1.发送远程调用，查询是否有库存；未处理；此处需要在看视频进行下一步操作
        try{
            //可能由于网络波动等原因，远程调用容易产生异常，所以进行try-catch处理
            R<List<SkuHasStockVo>> ware = wareFeignService.getSkuHasWare(skuList);
             stockMap=ware.getData().stream()
                    .collect(Collectors.toMap(SkuHasStockVo::getSkuId, item -> item.getHasStockVo()));
        }catch (Exception e)
        {
            log.error("库存远程调用出现异常",e);
        }
            //对es模型的属性进行封装
        Map<Long, Boolean> finalStockMap = stockMap;
        List<SkuEsModel> esModels = skus.stream().map((sku) -> {
            //对数据进行组装
            SkuEsModel model = new SkuEsModel();
            //对sku属性进行拷贝
            BeanUtils.copyProperties(sku,model);
            //以下属性需要额外处理：价格，图片路径，库存（未完成），热点评分，品牌名字，品牌图片，分类名
            model.setSkuPrice(sku.getPrice());
            model.setSkuImg(sku.getSkuDefaultImg());
               //有库存就是true，没有库存就是false
                if(finalStockMap ==null)
                {
                    model.setHasStock(true);
                }
                else {
                    model.setHasStock(finalStockMap.get(sku.getSkuId()));
                }

            //TODO:2.刚上架的商品热度默认为0，完成
            model.setHotScore(0L);
            //TODO:3.查询品牌的名字，品牌的图片以及分类名，完成
            BrandEntity brandEntity = brandService.getById(model.getBrandId());
            model.setBrandName(brandEntity.getName());
            model.setBrandImg(brandEntity.getLogo());
            CategoryEntity categoryEntity = categoryService.getById(model.getCatalogId());
            model.setCatalogName(categoryEntity.getName());
            model.setAttrs(attrs);
            return model;
        }).collect(Collectors.toList());
        //TODO:5.发送给es进行保存
        R r = searchFeignService.productStatusUp(esModels);
        if(r.getCode()==0)
        {
          //远程调用成功
            //todo:发布状态进行修改
            baseMapper.updateSpuStatus(spuId, ProductConstant.StatusEnum.ATTR_TYPE_UP.getCode());
        }else {
          //远程调用失败

            //TODO:7.重复调用？接口幂等性？重试机制

        }
    }
    @Override
    public SpuInfoEntity getSpuInfoBySkuId(Long skuId) {
        SkuInfoEntity byId = skuInfoService.getById(skuId);
        Long spuId = byId.getSpuId();
        SpuInfoEntity spuInfoEntity = getById(spuId);
        return spuInfoEntity;
    }
}